<template>
  <div class="app-container">
    <el-card class="box-card">
      <!-- 面包屑导航 -->
      <div class="breadcrumb-container">
        <el-breadcrumb separator="/">
          <el-breadcrumb-item :to="{ path: '/store/index' }">商品管理</el-breadcrumb-item>
          <el-breadcrumb-item>课程视频管理</el-breadcrumb-item>
        </el-breadcrumb>
        <el-button type="text" icon="el-icon-back" @click="goBack">返回</el-button>
      </div>

      <!-- 课程信息卡片 -->
      <div class="course-info-box" v-loading="courseLoading">
        <div class="course-image">
          <img :src="courseInfo.image || '/static/images/default-course.png'" alt="课程封面">
        </div>
        <div class="course-details">
          <h2 class="course-title">{{ courseInfo.storeName || '课程标题' }}</h2>
          <div class="course-meta">
            <span><i class="el-icon-video-camera"></i> 总课时: {{ courseInfo.totalEpisodes || 0 }}</span>
            <span><i class="el-icon-upload"></i> 已更新: {{ list.length || 0 }}</span>
            <span><i class="el-icon-time"></i> 类型: {{ courseInfo.courseType ? '线上课程' : '线下课程' }}</span>
          </div>
          <div class="course-desc">{{ courseInfo.storeInfo || '暂无课程简介' }}</div>
        </div>
      </div>

      <div class="filter-container">
        <el-button class="filter-item" type="primary" icon="el-icon-plus" @click="handleCreate">
          添加视频
        </el-button>
        <el-button class="filter-item" type="success" icon="el-icon-sort" @click="enableDragSort" v-if="!dragSortEnabled">
          排序模式
        </el-button>
        <el-button class="filter-item" type="info" icon="el-icon-check" @click="saveDragSort" v-else>
          保存排序
        </el-button>
        <el-input
          v-model="searchQuery"
          placeholder="搜索课时标题"
          style="width: 200px; margin-left: 10px;"
          class="filter-item"
          clearable
          @keyup.enter.native="handleFilter"
          @clear="handleFilter"
        >
          <i slot="prefix" class="el-input__icon el-icon-search" />
        </el-input>
      </div>

      <!-- 视频列表 -->
      <el-table
        v-loading="listLoading"
        :data="filteredList"
        element-loading-text="加载中..."
        border
        fit
        highlight-current-row
        row-key="id"
        :row-class-name="getRowClassName"
      >
        <el-table-column label="课时" width="80" align="center">
          <template slot-scope="scope">
            <span v-if="!dragSortEnabled">{{ scope.row.episodeNumber }}</span>
            <el-tag v-else type="info"><i class="el-icon-rank"></i></el-tag>
          </template>
        </el-table-column>

        <el-table-column label="课时标题" min-width="150">
          <template slot-scope="scope">
            <el-tooltip :content="scope.row.description || '无描述'" placement="top-start" :disabled="!scope.row.description">
              <span class="episode-title">{{ scope.row.title }}</span>
            </el-tooltip>
            <el-tag size="mini" type="success" v-if="scope.row.freePreview" class="ml-5">免费</el-tag>
          </template>
        </el-table-column>

        <el-table-column label="视频预览" width="200" align="center">
          <template slot-scope="scope">
            <div class="video-preview" @click="previewVideo(scope.row)" v-if="scope.row.videoUrl">
              <img :src="getFileUrl(scope.row.coverImage) || '/static/images/video-placeholder.png'" alt="视频封面">
              <div class="play-icon"><i class="el-icon-video-play"></i></div>
              <div class="duration-badge">{{ formatDuration(scope.row.duration) }}</div>
            </div>
            <span v-else>无视频</span>
          </template>
        </el-table-column>

        <el-table-column label="免费预览" width="90" align="center">
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.freePreview"
              active-color="#13ce66"
              inactive-color="#ff4949"
              @change="handleFreePreviewChange(scope.row)"
            />
          </template>
        </el-table-column>

        <el-table-column label="状态" width="90" align="center">
          <template slot-scope="scope">
            <el-switch
              v-model="scope.row.status"
              active-color="#13ce66"
              inactive-color="#ff4949"
              @change="handleStatusChange(scope.row)"
            />
          </template>
        </el-table-column>

        <el-table-column label="操作" width="220" align="center" fixed="right">
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="primary"
              icon="el-icon-edit"
              @click="handleUpdate(scope.row)"
              title="编辑"
            >
              编辑
            </el-button>
            <el-button
              size="mini"
              type="success"
              icon="el-icon-view"
              @click="previewVideo(scope.row)"
              title="预览"
              :disabled="!scope.row.videoUrl"
            >
              预览
            </el-button>
            <el-button
              size="mini"
              type="danger"
              icon="el-icon-delete"
              @click="handleDelete(scope.row)"
              title="删除"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div v-if="filteredList.length === 0 && !listLoading" class="empty-data">
        <el-empty :description="'暂无课程视频，请点击添加视频按钮创建课时'"></el-empty>
      </div>

      <div class="pagination-container">
        <el-pagination
          v-show="total>0"
          :current-page.sync="listQuery.page"
          :page-size.sync="listQuery.limit"
          :page-sizes="[10, 20, 30, 50]"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          background
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>

      <!-- 视频表单对话框 -->
      <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible" width="650px" :close-on-click-modal="false">
        <el-steps :active="dialogStepActive" finish-status="success" simple style="margin-bottom: 20px">
          <el-step title="基本信息" icon="el-icon-edit"></el-step>
          <el-step title="视频管理" icon="el-icon-upload"></el-step>
        </el-steps>

        <el-form
          ref="dataForm"
          :rules="rules"
          :model="temp"
          label-position="right"
          label-width="110px"
          class="form-container"
        >
          <!-- 步骤1：基本信息 -->
          <div v-show="dialogStepActive === 0">
            <el-form-item label="课时编号" prop="episodeNumber">
              <el-input-number v-model="temp.episodeNumber" :min="1" style="width: 120px" />
            </el-form-item>

            <el-form-item label="课时标题" prop="title">
              <el-input v-model="temp.title" placeholder="请输入课时标题" />
            </el-form-item>

            <el-form-item label="课时描述">
              <el-input v-model="temp.description" type="textarea" :rows="3" placeholder="请输入课时描述（选填）" />
            </el-form-item>

            <el-form-item label="排序值">
              <el-input-number v-model="temp.sort" :min="0" style="width: 120px" />
              <span class="form-tip">数值越小排序越靠前</span>
            </el-form-item>

            <el-form-item label="是否免费预览">
              <el-switch
                v-model="temp.freePreview"
                active-color="#13ce66"
                inactive-color="#ff4949"
                active-text="免费"
                inactive-text="付费"
              />
            </el-form-item>

            <el-form-item label="课时状态">
              <el-switch
                v-model="temp.status"
                active-color="#13ce66"
                inactive-color="#ff4949"
                active-text="显示"
                inactive-text="隐藏"
              />
            </el-form-item>
          </div>

          <!-- 步骤2：上传视频 -->
          <div v-show="dialogStepActive === 1">
            <el-alert
              title="选择一种方式添加视频"
              type="info"
              :closable="false"
              style="margin-bottom: 20px"
            >
            </el-alert>

            <el-tabs v-model="videoAddMethod" type="card">
              <el-tab-pane label="从媒体库选择" name="library">
                <el-form-item label="视频文件">
                  <div class="media-selector">
                    <div class="select-area" @click="openMediaLibrary('video')">
                      <div v-if="temp.videoUrl" class="media-preview">
                        <video :src="getFileUrl(temp.videoUrl)" class="preview-video"></video>
                        <div class="media-info">{{ temp.videoUrl.split('/').pop() }}</div>
                      </div>
                      <div v-else class="upload-placeholder">
                        <i class="el-icon-video-camera"></i>
                        <p>点击选择视频</p>
                      </div>
                    </div>
                    <el-button v-if="temp.videoUrl" type="text" @click="temp.videoUrl = ''" class="clear-btn">
                      清除选择
                    </el-button>
                  </div>
                </el-form-item>
              </el-tab-pane>

              <el-tab-pane label="上传视频" name="upload">
                <el-form-item label="视频文件">
                  <el-upload
                    class="video-uploader"
                    action=""
                    :http-request="uploadVideo"
                    :before-upload="beforeVideoUpload"
                    :show-file-list="false"
                    :accept="'video/*'"
                    :limit="1"
                  >
                    <div v-if="temp.videoUrl" class="video-preview-box">
                      <video :src="getFileUrl(temp.videoUrl)" class="preview-video" controls></video>
                      <div class="video-info">{{ temp.videoUrl.split('/').pop() }}</div>
                    </div>
                    <el-button v-else size="small" type="primary" icon="el-icon-upload">
                      选择视频文件
                    </el-button>
                  </el-upload>

                  <div v-if="temp.videoUrl" class="upload-actions">
                    <el-button type="text" size="mini" @click="temp.videoUrl = ''; videoFileList = []">
                      重新上传
                    </el-button>
                  </div>

                  <div class="upload-tip">
                    <i class="el-icon-info"></i> 支持mp4/mov/avi格式，建议使用mp4格式
                    <br>
                    <i class="el-icon-upload"></i> 大于100MB的视频将自动使用分片上传，支持断点续传
                  </div>

                  <div class="file-upload-status" v-if="uploadStatus.isUploading">
                    <el-progress :percentage="uploadStatus.percent" :status="uploadStatus.progressStatus === 'exception' ? 'exception' : (uploadStatus.progressStatus === 'success' ? 'success' : null)"></el-progress>
                    <div class="upload-tip">{{ uploadStatus.message }}</div>

                    <!-- 大文件上传详细信息 -->
                    <div v-if="uploadStatus.useBigFileUpload" class="big-file-upload-info">
                      <div class="upload-details">
                        <span>分片进度: {{ uploadStatus.uploadedChunks }}/{{ uploadStatus.totalChunks }}</span>
                        <span v-if="uploadStatus.uploadSpeed">上传速度: {{ uploadStatus.uploadSpeed }}</span>
                        <span v-if="uploadStatus.remainingTime">剩余时间: {{ uploadStatus.remainingTime }}</span>
                      </div>

                      <!-- 控制按钮 -->
                      <div class="upload-controls" v-if="uploadStatus.canPause">
                        <el-button
                          v-if="!uploadStatus.isPaused"
                          size="mini"
                          type="warning"
                          @click="pauseUpload"
                          icon="el-icon-video-pause"
                        >
                          暂停
                        </el-button>
                        <el-button
                          v-else
                          size="mini"
                          type="success"
                          @click="resumeUpload"
                          icon="el-icon-video-play"
                        >
                          继续
                        </el-button>
                        <el-button
                          size="mini"
                          type="danger"
                          @click="cancelUpload"
                          icon="el-icon-close"
                        >
                          取消
                        </el-button>
                      </div>
                    </div>
                  </div>
                </el-form-item>
              </el-tab-pane>

              <!-- <el-tab-pane label="外部视频" name="external">
                <el-form-item label="视频URL" prop="videoUrl">
                  <el-input v-model="temp.videoUrl" placeholder="输入视频URL链接">
                    <template slot="append">
                      <el-button @click="testVideoUrl">测试</el-button>
                    </template>
                  </el-input>
                  <div class="upload-tip">
                    <i class="el-icon-info"></i> 支持直接可访问的视频链接，例如第三方云存储的视频URL
                  </div>
                </el-form-item>
              </el-tab-pane> -->
            </el-tabs>

            <el-form-item label="视频封面">
              <div class="upLoadPicBox" @click="openImageLibrary">
                <div v-if="temp.coverImage" class="pictrue">
                  <img :src="getFileUrl(temp.coverImage)">
                </div>
                <div v-else class="upLoad">
                  <i class="el-icon-camera cameraIconfont" />
                </div>
              </div>
              <div v-if="temp.coverImage" class="preview-info">
                已上传: {{ temp.coverImage.split('/').pop() }}
                <el-button type="text" size="mini" @click="temp.coverImage = ''">重新上传</el-button>
              </div>
              <!-- 调试信息 -->
              <div class="debug-info" style="font-size: 12px; color: #999; margin-top: 5px;">
                调试: coverImage = "{{ temp.coverImage }}"
                <br>完整URL: {{ getFileUrl(temp.coverImage) }}
              </div>
              <div class="upload-tip">
                <i class="el-icon-info"></i> 建议尺寸16:9，JPG/PNG格式，大小不超过2MB
              </div>
            </el-form-item>

            <el-form-item label="视频时长">
              <el-time-picker
                v-model="videoDuration"
                format="mm:ss"
                placeholder="请选择时长"
                style="width: 120px"
                @change="updateDuration"
              ></el-time-picker>
              <span class="form-tip">或直接输入秒数：</span>
              <el-input-number v-model="temp.duration" :min="0" style="width: 120px"></el-input-number>
              <span class="form-tip">秒</span>
            </el-form-item>

            <!-- 视频预览 -->
            <el-form-item label="预览效果" v-if="temp.videoUrl">
              <div class="preview-video-container">
                <img :src="getFileUrl(temp.coverImage) || '/static/images/video-placeholder.png'" class="preview-cover">
                <div class="preview-play-icon" @click="previewVideo(temp)">
                  <i class="el-icon-video-play"></i>
                </div>
                <div class="video-info-overlay">
                  <p class="video-title">{{ temp.title }}</p>
                  <p class="video-duration">{{ formatDuration(temp.duration) }}</p>
                </div>
              </div>
            </el-form-item>

            <!-- 调试和帮助区域 -->
            <div class="debug-area">
              <el-divider content-position="left">调试与帮助</el-divider>
              <div class="debug-buttons">
                <el-button type="text" @click="checkServerStatus" size="small">
                  <i class="el-icon-connection"></i> 检查服务器连接
                </el-button>
                <el-button type="text" @click="applyTestVideo" size="small">
                  <i class="el-icon-video-camera"></i> 应用测试视频
                </el-button>
                <el-button type="text" @click="showUploadHelp = !showUploadHelp" size="small">
                  <i class="el-icon-question"></i> 上传问题帮助
                </el-button>
              </div>

              <el-collapse-transition>
                <div v-show="showUploadHelp" class="help-content">
                  <h4>如果遇到上传问题，请检查以下事项：</h4>
                  <ol>
                    <li><strong>服务器状态：</strong>确认后端服务运行在 http://127.0.0.1:20010</li>
                    <li><strong>文件大小：</strong>视频文件不要超过系统限制（通常100MB）</li>
                    <li><strong>文件格式：</strong>确认使用支持的视频格式（mp4/mov/avi）</li>
                    <li><strong>网络连接：</strong>检查本地网络连接是否正常</li>
                    <li><strong>防火墙：</strong>确认防火墙没有阻止20010端口</li>
                  </ol>
                  <p><strong>当前配置：</strong></p>
                  <ul>
                    <li>上传地址：{{ getUploadUrl() }}</li>
                    <li>认证Token：{{ hasToken() ? '已设置' : '未设置' }}</li>
                  </ul>
                </div>
              </el-collapse-transition>
            </div>
          </div>
        </el-form>

        <div slot="footer" class="dialog-footer">
          <el-button @click="dialogStepActive > 0 ? dialogStepActive-- : dialogFormVisible = false">
            {{ dialogStepActive > 0 ? '上一步' : '取消' }}
          </el-button>
          <el-button v-if="dialogStepActive < 1" type="primary" @click="nextStep">
            下一步
          </el-button>
          <el-button v-else type="primary" @click="submitForm()">
            {{ isEdit ? '保存修改' : '添加课时' }}
          </el-button>
        </div>
      </el-dialog>

      <!-- 视频预览弹窗 -->
      <el-dialog
        title="视频预览"
        :visible.sync="videoPreviewVisible"
        width="800px"
        custom-class="video-preview-dialog"
        :close-on-click-modal="false"
        :append-to-body="true"
      >
        <div class="video-container">
          <!-- 使用iframe作为备用方案 -->
          <iframe
            v-if="previewVideoUrl && useIframe"
            :src="previewVideoUrl"
            frameborder="0"
            allowfullscreen
            class="preview-video-player"
          ></iframe>

          <!-- 原始视频播放器 -->
          <video
            v-else-if="previewVideoUrl"
            :src="previewVideoUrl"
            controls
            autoplay
            class="preview-video-player"
            @error="handleVideoError"
            @loadedmetadata="onVideoLoaded"
            @loadstart="handleVideoLoadStart"
            @canplay="handleVideoCanPlay"
          ></video>

          <div v-else class="empty-video">
            <i class="el-icon-video-camera"></i>
            <p>无可播放的视频</p>
          </div>
        </div>
        <div class="dialog-footer" slot="footer">
          <!-- 添加调试信息 -->
          <!-- <div class="video-debug-info" style="margin-bottom: 10px; word-break: break-all;">
            <div><strong>当前视频URL:</strong> {{ previewVideoUrl }}</div>
            <div><strong>原始路径:</strong> {{ previewVideoInfo ? previewVideoInfo.videoUrl : '无' }}</div>
          </div> -->

          <el-button @click="videoPreviewVisible = false">关闭</el-button>
          <el-button type="primary" @click="openVideoInNewTab">在新窗口打开</el-button>
          <el-button type="success" @click="downloadVideo">下载视频</el-button>
          <el-dropdown @command="tryDifferentUrl">
            <el-button type="warning">
              尝试不同URL格式 <i class="el-icon-arrow-down el-icon--right"></i>
            </el-button>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item command="format1">格式1: 基础URL+路径</el-dropdown-item>
              <el-dropdown-item command="format2">格式2: 基础URL+无file前缀</el-dropdown-item>
              <el-dropdown-item command="format3">格式3: 基础URL+api前缀</el-dropdown-item>
              <el-dropdown-item command="format4">格式4: 基础URL+public</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </el-dialog>
    </el-card>
  </div>
</template>

<script>
import { getCourseVideoList, addCourseVideo, updateCourseVideo, deleteCourseVideo } from '@/api/course'
import { productDetailApi } from '@/api/store'
import {
  fileFileApi,
  checkBigFileExistsApi,
  uploadBigFileChunkApi,
  mergeBigFileChunksApi,
  cancelBigFileUploadApi
} from '@/api/systemSetting'

export default {
  name: 'CourseVideo',

  components: {
  },

  data() {
    return {
      courseId: null,
      courseInfo: {},
      courseLoading: false,
      list: [],
      filteredList: [],
      total: 0,
      listLoading: true,
      dialogFormVisible: false,
      dialogTitle: '',
      dialogStepActive: 0,
      isEdit: false,
      temp: {
        id: undefined,
        courseId: undefined,
        episodeNumber: 1,
        title: '',
        videoUrl: '',
        coverImage: '',
        duration: 0,
        description: '',
        freePreview: false,
        sort: 0,
        status: true
      },
      rules: {
        episodeNumber: [{ required: true, message: '课时编号不能为空', trigger: 'blur' }],
        title: [{ required: true, message: '课时标题不能为空', trigger: 'blur' }],
        videoUrl: [{ required: false, message: '视频URL不能为空', trigger: 'blur' }]
      },
      videoFileList: [],
      listQuery: {
        page: 1,
        limit: 20
      },
      searchQuery: '',
      videoDuration: new Date(0, 0, 0, 0, 0, 0),
      videoPreviewVisible: false,
      previewVideoUrl: '',
      previewVideoInfo: null,
      dragSortEnabled: false,
      uploadHeaders: {
        'Authorization': localStorage.getItem('token') || ''
      },
      videoAddMethod: 'upload',
      uploadStatus: {
        isUploading: false,
        percent: 0,
        progressStatus: '',
        message: '准备上传...',
        // 大文件上传相关属性
        useBigFileUpload: false,
        currentFile: null,
        fileIdentifier: '',
        chunkSize: 5 * 1024 * 1024, // 5MB分片大小
        totalChunks: 0,
        uploadedChunks: 0,
        uploadSpeed: 0,
        remainingTime: 0,
        canPause: false,
        isPaused: false,
        uploadedChunkNumbers: []
      },
      showUploadHelp: false,
      selectedUploadApi: '/admin/upload/file',
      useIframe: false,
      uploadStartTime: null, // 添加上传开始时间
    }
  },
  created() {
    this.courseId = this.$route.params.id
    this.getCourseInfo()
    this.getList()
  },
  methods: {
    getCourseInfo() {
      this.courseLoading = true
      productDetailApi(this.courseId).then(res => {
        if (res.data) {
          this.courseInfo = res.data.productInfo || res.data
        }
        this.courseLoading = false
      }).catch(() => {
        this.courseLoading = false
      })
    },
    getList() {
      this.listLoading = true
      getCourseVideoList(this.courseId, this.listQuery).then(response => {
        if (response && response.list) {
          this.list = response.list
          this.filteredList = [...this.list]
          this.total = response.total || 0
        } else {
          this.list = []
          this.filteredList = []
          this.total = 0
        }
        this.listLoading = false
      }).catch(() => {
        this.list = []
        this.filteredList = []
        this.total = 0
        this.listLoading = false
      })
    },
    // 搜索筛选
    handleFilter() {
      if (!this.searchQuery) {
        this.filteredList = [...this.list]
      } else {
        const query = this.searchQuery.toLowerCase()
        this.filteredList = this.list.filter(item => {
          return item.title.toLowerCase().includes(query) ||
                 (item.description && item.description.toLowerCase().includes(query))
        })
      }
    },
    // 拖拽排序相关
    enableDragSort() {
      this.dragSortEnabled = true
      this.$message.info('已进入排序模式，拖动行可调整顺序，完成后请点击"保存排序"')
    },
    saveDragSort() {
      this.dragSortEnabled = false
      this.$message.success('排序已保存')
    },
    getRowClassName() {
      return this.dragSortEnabled ? 'draggable-row' : ''
    },
    // 返回上一页
    goBack() {
      this.$router.go(-1)
    },
    // 格式化时长显示
    formatDuration(seconds) {
      if (!seconds) return '00:00'
      const minutes = Math.floor(seconds / 60)
      const remainingSeconds = seconds % 60
      return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
    },
    // 更新时长（从时间选择器）
    updateDuration(time) {
      if (time) {
        const minutes = time.getMinutes()
        const seconds = time.getSeconds()
        this.temp.duration = minutes * 60 + seconds
      }
    },
    resetTemp() {
      this.temp = {
        id: undefined,
        courseId: this.courseId,
        episodeNumber: this.list.length > 0 ? Math.max(...this.list.map(v => v.episodeNumber)) + 1 : 1,
        title: '',
        videoUrl: '',
        coverImage: '',
        duration: 0,
        description: '',
        freePreview: false,
        sort: 0,
        status: true
      }
      this.videoFileList = []
      this.videoDuration = new Date(0, 0, 0, 0, 0, 0)
      this.dialogStepActive = 0
      this.videoAddMethod = 'upload'
      this.uploadStatus = {
        isUploading: false,
        percent: 0,
        progressStatus: '',
        message: '准备上传...',
        // 大文件上传相关属性
        useBigFileUpload: false,
        currentFile: null,
        fileIdentifier: '',
        chunkSize: 5 * 1024 * 1024, // 5MB分片大小
        totalChunks: 0,
        uploadedChunks: 0,
        uploadSpeed: 0,
        remainingTime: 0,
        canPause: false,
        isPaused: false,
        uploadedChunkNumbers: []
      }
    },
    nextStep() {
      if (this.dialogStepActive === 0) {
        // 只验证基本信息字段
        this.$refs.dataForm.validateField(['episodeNumber', 'title'], (valid) => {
          if (valid === '') {
            this.dialogStepActive++
          }
        })
      }
    },
    handleCreate() {
      this.resetTemp()
      this.dialogTitle = '添加课时视频'
      this.dialogFormVisible = true
      this.isEdit = false

      // 延迟执行表单验证清除
      setTimeout(() => {
        if (this.$refs['dataForm']) {
          this.$refs['dataForm'].clearValidate()
        }
      }, 100)
    },
    handleUpdate(row) {
      this.temp = Object.assign({}, row)

      // 如果有视频，添加到文件列表
      if (this.temp.videoUrl) {
        // 从URL提取文件名
        const fileName = this.temp.videoUrl.split('/').pop() || '视频文件.mp4'
        this.videoFileList = [{
          name: fileName,
          url: this.temp.videoUrl
        }]
      } else {
        this.videoFileList = []
      }

      // 设置时间选择器的值
      const minutes = Math.floor(this.temp.duration / 60)
      const seconds = this.temp.duration % 60
      this.videoDuration = new Date(0, 0, 0, 0, minutes, seconds)

      this.dialogTitle = '编辑课时视频'
      this.dialogFormVisible = true
      this.isEdit = true
      this.dialogStepActive = 0
      this.$nextTick(() => {
        this.$refs['dataForm'].clearValidate()
      })
    },
    handleDelete(row) {
      this.$confirm(`确认删除课时"${row.title}"?`, '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        deleteCourseVideo(row.id).then(() => {
          this.$notify({
            title: '成功',
            message: '删除成功',
            type: 'success',
            duration: 2000
          })
          this.getList()
        })
      })
    },
    handleStatusChange(row) {
      const temp = Object.assign({}, row)
      updateCourseVideo(temp).then(() => {
        this.$message({
          message: row.status ? '课时已显示' : '课时已隐藏',
          type: 'success'
        })
      })
    },
    handleFreePreviewChange(row) {
      const temp = Object.assign({}, row)
      updateCourseVideo(temp).then(() => {
        this.$message({
          message: row.freePreview ? '已设为免费预览' : '已取消免费预览',
          type: 'success'
        })
      })
    },
    // 图片上传前的验证
    beforeImageUpload(file) {
      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
      const isLt2M = file.size / 1024 / 1024 < 2

      if (!isJPG) {
        this.$message.error('上传封面只能是 JPG/PNG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上传封面大小不能超过 2MB!')
      }
      return isJPG && isLt2M
    },
    // 封面上传成功回调
    handleCoverSuccess(url) {
      if (url) {
        this.temp.coverImage = url
        console.log('封面上传成功，URL:', url)
        this.$message.success('封面上传成功')
      } else {
        this.$message.error('封面上传失败：未获取到有效URL')
      }
    },
    // 视频上传前验证
    beforeVideoUpload(file) {
      // 显示上传状态
      this.uploadStatus.isUploading = true
      this.uploadStatus.percent = 0
      this.uploadStatus.progressStatus = 'active'
      this.uploadStatus.message = '准备上传...'

      const isVideo = file.type.includes('video') ||
                      file.name.endsWith('.mp4') ||
                      file.name.endsWith('.mov') ||
                      file.name.endsWith('.avi')

      if (!isVideo) {
        this.$message.error('请上传视频格式的文件!')
        this.uploadStatus.isUploading = false
        return false
      }

      // 模拟上传进度
      this.uploadProgressTimer = setInterval(() => {
        if (this.uploadStatus.percent < 99) {
          const newPercent = this.uploadStatus.percent + Math.floor(Math.random() * 10) + 2
          this.uploadStatus.percent = Math.min(newPercent, 99) // 修复：确保进度不超过99%
          this.uploadStatus.message = `上传中 ${this.uploadStatus.percent}%...`
        }
      }, 800)

      return true
    },
    // 视频上传成功回调
    handleVideoSuccess(response) {
      clearInterval(this.uploadProgressTimer)
      this.uploadStatus.percent = 100
      this.uploadStatus.progressStatus = 'success'
      this.uploadStatus.message = '上传完成'

      console.log('视频上传响应:', response)

      // 直接使用返回的路径，无需附加域名
      let url = ''
      if (response && response.url) {
        url = response.url
      } else if (response && response.data && response.data.url) {
        url = response.data.url
      }

      if (url) {
        // 保存相对路径，不添加域名
        this.temp.videoUrl = url

        // 提取文件名
        const fileName = url.split('/').pop() || '视频文件.mp4'
        this.videoFileList = [{
          name: fileName,
          url: url
        }]

        this.$message.success('视频上传成功')

        // 自动获取视频时长
        this.getVideoDuration(url)
      } else {
        this.uploadStatus.progressStatus = 'exception'
        this.uploadStatus.message = '上传失败：服务器未返回有效URL'
        this.$message.error('视频上传失败：未获取到有效URL')
      }

      setTimeout(() => {
        this.uploadStatus.isUploading = false
      }, 1500)
    },
    // 上传错误处理
    handleUploadError(err) {
      this.uploadStatus.percent = 100
      this.uploadStatus.progressStatus = 'exception'

      let errorMessage = '上传失败，请检查网络或服务器状态'
      if (err && typeof err === 'object') {
        errorMessage = err.message || errorMessage
      }

      this.uploadStatus.message = '上传失败'
      this.$message.error(errorMessage)

      setTimeout(() => {
        this.uploadStatus.isUploading = false
      }, 1500)
    },
    // 上传进度处理
    handleUploadProgress(event, file, fileList) {
      if (event.percent) {
        this.uploadStatus.percent = Math.round(event.percent)
        this.uploadStatus.message = `上传中 ${this.uploadStatus.percent}%...`
      }
    },
    // 视频预览
    previewVideo(video) {
      if (!video || !video.videoUrl) {
        this.$message.warning('没有可播放的视频')
        return
      }

      // 处理原始路径
      let videoUrl = video.videoUrl

      // 如果路径以斜杠开头且后面跟着http，直接去掉斜杠
      if (videoUrl.startsWith('/http')) {
        videoUrl = videoUrl.substring(1)
        // 同时修正原始对象中的URL
        if (this.isEdit && video === this.temp) {
          this.temp.videoUrl = videoUrl
        }
      }

      // 记录日志
      console.log('预览视频对象:', video)
      console.log('处理后的原始视频路径:', videoUrl)

      // 对所有URL使用getFileUrl处理，包括以http开头的URL，因为它们可能包含重复域名
      this.previewVideoUrl = this.getFileUrl(videoUrl)
      this.previewVideoInfo = { ...video, videoUrl }
      this.videoPreviewVisible = true
      this.useIframe = false

      console.log('最终预览视频URL:', this.previewVideoUrl)
    },
    // 测试视频URL
    testVideoUrl() {
      if (!this.temp.videoUrl) {
        this.$message.warning('请先输入视频URL')
        return
      }

      // 尝试预览视频
      this.previewVideo(this.temp)
    },
    // 应用测试视频
    applyTestVideo() {
      this.temp.videoUrl = 'https://www.w3schools.com/html/mov_bbb.mp4' // 使用公开的测试视频
      this.temp.coverImage = 'https://picsum.photos/320/180' // 使用随机图片作为封面
      this.temp.duration = 60 // 设置为1分钟
      this.videoDuration = new Date(0, 0, 0, 0, 1, 0)

      this.videoFileList = [{
        name: '测试视频.mp4',
        url: this.temp.videoUrl
      }]

      this.$message.success('已应用测试视频，点击预览可查看效果')
    },
    // 更改上传API路径
    changeUploadApi(path) {
      // 这里仅修改组件属性，实际使用时可能需要直接修改DOM
      this.$nextTick(() => {
        const uploadComponent = this.$el.querySelector('.video-uploader .el-upload')
        if (uploadComponent) {
          uploadComponent.setAttribute('action', path)
          this.$message.info(`已将上传路径切换为 ${path}`)
        }
      })
    },
    // 提交表单
    submitForm() {
      if (!this.temp.videoUrl) {
        this.$message.warning('请先上传或选择视频')
        return
      }

      // 处理视频URL，如果以/http开头，去掉斜杠
      if (this.temp.videoUrl.startsWith('/http')) {
        this.temp.videoUrl = this.temp.videoUrl.substring(1)
      }

      // 已经是完整URL的情况下，不做处理
      if (!this.temp.videoUrl.startsWith('http')) {
        this.temp.videoUrl = this.formatFileUrl(this.temp.videoUrl, false)
      }

      // 处理封面图URL
      if (this.temp.coverImage) {
        if (this.temp.coverImage.startsWith('/http')) {
          this.temp.coverImage = this.temp.coverImage.substring(1)
        }

        if (!this.temp.coverImage.startsWith('http')) {
          this.temp.coverImage = this.formatFileUrl(this.temp.coverImage, false)
        }
      }

      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          const loadingInstance = this.$loading({
            lock: true,
            text: this.isEdit ? '正在保存...' : '正在添加...',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          })

          // 确保课程ID设置正确
          this.temp.courseId = this.courseId

          if (this.isEdit) {
            updateCourseVideo(this.temp).then(() => {
              loadingInstance.close()
              this.dialogFormVisible = false
              this.$notify({
                title: '成功',
                message: '更新成功',
                type: 'success',
                duration: 2000
              })
              this.getList()
            }).catch((err) => {
              loadingInstance.close()
              this.$message.error('保存失败：' + (err.message || '未知错误'))
            })
          } else {
            addCourseVideo(this.temp).then(() => {
              loadingInstance.close()
              this.dialogFormVisible = false
              this.$notify({
                title: '成功',
                message: '创建成功',
                type: 'success',
                duration: 2000
              })
              this.getList()
            }).catch((err) => {
              loadingInstance.close()
              this.$message.error('添加失败：' + (err.message || '未知错误'))
            })
          }
        }
      })
    },
    handleSizeChange(val) {
      this.listQuery.limit = val
      this.getList()
    },
    handleCurrentChange(val) {
      this.listQuery.page = val
      this.getList()
    },
    uploadVideo(options) {
      const file = options.file
      const fileSize = file.size
      const fileSizeInMB = fileSize / (1024 * 1024)

      // 优先使用原有的API方法，更稳定
      if (fileSizeInMB > 100) { // 大文件使用分片上传
        this.uploadStatus.useBigFileUpload = true
        this.uploadBigFile(file, options)
      } else {
        this.uploadStatus.useBigFileUpload = false
        // 使用稳定的API方法
        this.uploadSmallFileStable(file, options)
      }
    },

    // 使用稳定的API方法上传小文件
    uploadSmallFileStable(file, options) {
      this.uploadStatus.isUploading = true
      this.uploadStatus.percent = 0
      this.uploadStatus.progressStatus = 'active'
      this.uploadStatus.message = '准备上传...'

      // 创建FormData对象 - 只包含文件
      const formData = new FormData()
      formData.append('multipart', file)  // ✅ 修复1：改为 'multipart'

      // 查询参数单独传递 - 按照其他组件的方式
      const queryParams = {
        model: 'course',
        pid: 1,  // ✅ 修复2：使用数字而不是字符串
      }

      console.log('开始上传文件，大小:', this.formatFileSize(file.size))
      console.log('上传参数:', {
        fileName: file.name,
        fileSize: file.size,
        fileType: file.type,
        model: 'course',
        pid: 1
      })

      // 模拟上传进度
      let progressInterval = setInterval(() => {
        if (this.uploadStatus.percent < 99) {
          const newPercent = this.uploadStatus.percent + Math.floor(Math.random() * 10) + 2
          this.uploadStatus.percent = Math.min(newPercent, 99) // 修复：确保进度不超过99%
          this.uploadStatus.message = `上传中 ${this.uploadStatus.percent}%...`
        }
      }, 800)

      // ✅ 修复：按照实际返回格式判断
      fileFileApi(formData, queryParams).then(res => {
        clearInterval(progressInterval)
        
        console.log('上传响应:', res)
        
        this.uploadStatus.percent = 100
        this.uploadStatus.progressStatus = 'success'
        this.uploadStatus.message = '上传完成'

        // ✅ 修复：直接检查 url 字段（因为 request.js 已经解析了 CommonResult）
        if (res && res.url) {
          this.temp.videoUrl = res.url
          this.videoFileList = [{
            name: file.name,
            url: res.url
          }]
          this.$message.success('视频上传成功')
          
          // 自动获取视频时长
          this.getVideoDuration(res.url)
          
          options.onSuccess(res)
        } else {
          this.uploadStatus.progressStatus = 'exception'
          const errorMsg = '服务器未返回有效的文件URL'
          this.uploadStatus.message = '上传失败：' + errorMsg
          this.$message.error('上传失败：' + errorMsg)
          console.error('上传失败，服务器响应:', res)
          options.onError(new Error(errorMsg))
        }

        setTimeout(() => {
          this.uploadStatus.isUploading = false
        }, 1500)
        
      }).catch(err => {
        // 错误处理保持不变
        clearInterval(progressInterval)
        
        console.error('上传请求失败:', err)
        
        this.uploadStatus.progressStatus = 'exception'
        this.uploadStatus.message = '上传失败'
        
        let errorMessage = '未知错误'
        
        if (err.code === 'ERR_NETWORK' || err.message.includes('Network Error')) {
          errorMessage = '网络连接失败，请检查服务器是否运行'
        } else if (err.code === 'ECONNABORTED' || err.message.includes('timeout')) {
          errorMessage = '上传超时，请尝试上传更小的文件'
        } else if (err.response) {
          if (err.response.status === 413) {
            errorMessage = '文件太大，超过服务器限制'
          } else if (err.response.status === 415) {
            errorMessage = '不支持的文件格式'
          } else if (err.response.status >= 500) {
            errorMessage = '服务器内部错误'
          } else {
            const responseMessage = err.response.data && err.response.data.message
              ? err.response.data.message 
              : err.response.statusText
            errorMessage = `服务器错误 ${err.response.status}: ${responseMessage}`
          }
        } else if (err.message) {
          errorMessage = err.message
        }
        
        this.$message.error('上传失败：' + errorMessage)
        options.onError(err)
        
        setTimeout(() => {
          this.uploadStatus.isUploading = false
        }, 1500)
      })
    },

    // 大文件分片上传
    async uploadBigFile(file, options) {
      try {
        this.uploadStatus.isUploading = true
        this.uploadStatus.currentFile = file
        this.uploadStatus.canPause = true
        this.uploadStatus.isPaused = false
        this.uploadStatus.progressStatus = 'active'

        // 生成文件唯一标识符
        this.uploadStatus.fileIdentifier = this.generateFileIdentifier(file)

        // 计算分片信息
        const chunkSize = this.uploadStatus.chunkSize
        const totalChunks = Math.ceil(file.size / chunkSize)
        this.uploadStatus.totalChunks = totalChunks
        this.uploadStatus.uploadedChunks = 0

        this.uploadStatus.message = '检查文件状态...'
        console.log('开始大文件上传，文件大小:', this.formatFileSize(file.size), '总分片数:', totalChunks)

        // 检查文件是否已存在或部分上传
        const checkResult = await checkBigFileExistsApi(this.uploadStatus.fileIdentifier)
        console.log('文件检查结果:', checkResult)

        if (checkResult.code === 200 && checkResult.data && checkResult.data.completed) {
          // 文件已完全上传
          this.uploadStatus.percent = 100
          this.uploadStatus.progressStatus = 'success'
          this.uploadStatus.message = '文件已存在，上传完成'
          this.temp.videoUrl = checkResult.data.fileResult.url
          this.videoFileList = [{
            name: file.name,
            url: checkResult.data.fileResult.url
          }]
          this.$message.success('视频上传成功（文件已存在）')
          options.onSuccess(checkResult)
          this.uploadStatus.isUploading = false
          return
        }

        // 获取已上传的分片
        this.uploadStatus.uploadedChunkNumbers = (checkResult.code === 200 && checkResult.data && checkResult.data.uploadedChunkNumbers) ? checkResult.data.uploadedChunkNumbers : []
        this.uploadStatus.uploadedChunks = this.uploadStatus.uploadedChunkNumbers.length

        console.log('已上传分片:', this.uploadStatus.uploadedChunkNumbers.length, '/', totalChunks)

        this.uploadStatus.message = '开始分片上传...'

        // 开始上传分片
        await this.uploadChunks(file, options)

      } catch (error) {
        console.error('大文件上传失败:', error)
        this.uploadStatus.progressStatus = 'exception'
        this.uploadStatus.message = '上传失败'

        // 提取错误信息
        let errorMessage = '未知错误'
        if (error && error.message) {
          errorMessage = error.message
        } else if (error && typeof error === 'string') {
          errorMessage = error
        } else if (error && error.msg) {
          errorMessage = error.msg
        } else if (error && error.response && error.response.data) {
          errorMessage = error.response.data.message || error.response.data.msg || '服务器错误'
        }

        this.$message.error('上传失败：' + errorMessage)
        options.onError(error)
        this.uploadStatus.isUploading = false
      }
    },

    // 上传分片
    async uploadChunks(file, options) {
      const chunkSize = this.uploadStatus.chunkSize
      const totalChunks = this.uploadStatus.totalChunks
      const uploadedChunks = this.uploadStatus.uploadedChunkNumbers

      const startTime = Date.now()
      let uploadedBytes = uploadedChunks.length * chunkSize

      for (let chunkNumber = 0; chunkNumber < totalChunks; chunkNumber++) {
        // 检查是否暂停
        if (this.uploadStatus.isPaused) {
          this.uploadStatus.message = '上传已暂停'
          return
        }

        // 跳过已上传的分片
        if (uploadedChunks.includes(chunkNumber)) {
          uploadedBytes += chunkSize
          continue
        }

        const start = chunkNumber * chunkSize
        const end = Math.min(start + chunkSize, file.size)
        const chunk = file.slice(start, end)

        const formData = new FormData()
        formData.append('file', chunk)
        formData.append('identifier', this.uploadStatus.fileIdentifier)
        formData.append('filename', file.name)
        formData.append('chunkNumber', chunkNumber.toString())
        formData.append('chunkSize', chunkSize.toString())
        formData.append('currentChunkSize', chunk.size.toString())
        formData.append('totalSize', file.size.toString())
        formData.append('totalChunks', totalChunks.toString())
        formData.append('type', file.type || 'video/mp4')
        formData.append('model', 'course')
        formData.append('pid', '1')

        // 分片上传重试机制
        let retryCount = 0
        const maxRetries = 3
        let uploadSuccess = false

        while (retryCount < maxRetries && !uploadSuccess) {
          try {
            console.log(`上传分片 ${chunkNumber}/${totalChunks - 1}，重试次数: ${retryCount}`)
            const result = await uploadBigFileChunkApi(formData)

            // 检查API响应 - 更智能的成功判断
            const isSuccess = result.code === 200 ||
                             result.code === 0 ||
                             (result.message && result.message.includes('成功')) ||
                             (result.msg && result.msg.includes('成功')) ||
                             result.success === true

            if (!isSuccess) {
              throw new Error(result.message || result.msg || `分片 ${chunkNumber} 上传失败`)
            }

            // 上传成功
            uploadSuccess = true
            this.uploadStatus.uploadedChunks++
            this.uploadStatus.uploadedChunkNumbers.push(chunkNumber)
            uploadedBytes += chunk.size

            const progress = (this.uploadStatus.uploadedChunks / totalChunks) * 100
            this.uploadStatus.percent = Math.round(progress)

            // 计算上传速度和剩余时间
            const elapsedTime = (Date.now() - startTime) / 1000
            if (elapsedTime > 0) {
              const speed = uploadedBytes / elapsedTime // bytes/second
              const remainingBytes = file.size - uploadedBytes
              const remainingTime = remainingBytes / speed

              this.uploadStatus.uploadSpeed = this.formatSpeed(speed)
              this.uploadStatus.remainingTime = this.formatTime(remainingTime)
              this.uploadStatus.message = `上传中 ${this.uploadStatus.percent}% (${this.uploadStatus.uploadSpeed})`
            }

            console.log(`分片 ${chunkNumber} 上传成功，进度: ${this.uploadStatus.percent}%`)

          } catch (error) {
            retryCount++
            console.error(`分片 ${chunkNumber} 上传失败 (第${retryCount}次重试):`, error)

            if (retryCount >= maxRetries) {
              throw new Error(`分片 ${chunkNumber} 上传失败，已重试 ${maxRetries} 次: ${error.message || error}`)
            }

            // 等待一段时间后重试
            await new Promise(resolve => setTimeout(resolve, 1000 * retryCount))
          }
        }
      }

      // 所有分片上传完成，合并文件
      console.log('所有分片上传完成，开始合并文件...')
      await this.mergeChunks(file, options)
    },

    // 合并分片
    async mergeChunks(file, options) {
      console.log('开始合并分片，文件标识符:', this.uploadStatus.fileIdentifier)
      this.uploadStatus.message = '正在合并文件，请稍候...'
      this.uploadStatus.percent = 99 // 显示99%，等合并完成后显示100%

      try {
        const mergeParams = {
          identifier: this.uploadStatus.fileIdentifier,
          filename: file.name,
          totalChunks: this.uploadStatus.totalChunks,
          totalSize: file.size,
          type: file.type || 'video/mp4',
          model: 'course',
          pid: 1
        }

        console.log('合并参数:', mergeParams)

        // 合并也添加重试机制
        let retryCount = 0
        const maxRetries = 3
        let mergeSuccess = false
        let result = null

        while (retryCount < maxRetries && !mergeSuccess) {
          try {
            console.log(`尝试合并文件，重试次数: ${retryCount}`)
            result = await mergeBigFileChunksApi(mergeParams)
            console.log('合并API响应:', result)

            // 检查API响应 - 更完善的成功判断
            if (result.code === 200 || result.code === 0 || result.success === true) {
              mergeSuccess = true
            } else if (result.completed === true) {
              // 如果completed为true，说明文件已经合并完成
              mergeSuccess = true
              console.log('文件已完成合并，completed为true')
            } else {
              throw new Error(result.message || result.msg || '文件合并失败')
            }
          } catch (error) {
            retryCount++
            console.error(`文件合并失败 (第${retryCount}次重试):`, error)

            if (retryCount >= maxRetries) {
              throw error
            }

            // 等待一段时间后重试
            await new Promise(resolve => setTimeout(resolve, 2000 * retryCount))
          }
        }

        // 处理合并成功后的响应
        if (result.completed === true) {
          // 文件已完成，需要从响应中获取文件信息
          console.log('文件合并完成，处理响应数据')
          console.log('fileResult详细信息:', result.fileResult)
          this.uploadStatus.percent = 100
          this.uploadStatus.progressStatus = 'success'
          this.uploadStatus.message = '上传完成'

          // 尝试从不同的响应字段获取文件URL
          let fileUrl = ''
          if (result.fileResult && result.fileResult.url) {
            fileUrl = result.fileResult.url
          } else if (result.fileResult && result.fileResult.filePath) {
            fileUrl = result.fileResult.filePath
          } else if (result.fileResult && result.fileResult.fileUrl) {
            fileUrl = result.fileResult.fileUrl
          } else if (result.fileResult && result.fileResult.path) {
            fileUrl = result.fileResult.path
          } else if (result.data && result.data.fileResult && result.data.fileResult.url) {
            fileUrl = result.data.fileResult.url
          } else if (result.data && result.data.url) {
            fileUrl = result.data.url
          } else if (result.url) {
            fileUrl = result.url
          } else if (result.filePath) {
            fileUrl = result.filePath
          }

          if (fileUrl) {
            console.log('文件合并成功，文件URL:', fileUrl)
            this.temp.videoUrl = fileUrl
            this.videoFileList = [{
              name: file.name,
              url: fileUrl
            }]

            this.$message.success('视频上传成功')
            this.getVideoDuration(fileUrl)
            options.onSuccess(result)
          } else {
            console.error('合并完成但未找到文件URL，完整响应:', result)
            console.error('fileResult对象:', result.fileResult)

            // 如果没有找到URL，但文件确实已完成，我们可以尝试构建URL
            if (result.fileResult && result.fileResult.fileName) {
              // 尝试使用文件名构建URL（这需要根据你的后端逻辑调整）
              const fileName = result.fileResult.fileName
              console.log('尝试使用文件名构建URL:', fileName)

              // 先显示成功，但提示用户手动设置URL
              this.$message.success('文件上传完成，但需要手动设置视频URL')
              this.temp.videoUrl = '' // 暂时留空，让用户手动输入

              // 显示文件信息供用户参考
              this.$message.info(`上传的文件：${fileName}，大小：${this.formatFileSize(result.fileResult.fileSize || 0)}`)

              options.onSuccess(result)
            } else {
              throw new Error('文件合并完成但未获取到文件信息')
            }
          }
        } else if (result.data && result.data.completed && result.data.fileResult) {
          console.log('文件合并成功，文件URL:', result.data.fileResult.url)
          this.uploadStatus.percent = 100
          this.uploadStatus.progressStatus = 'success'
          this.uploadStatus.message = '上传完成'

          this.temp.videoUrl = result.data.fileResult.url
          this.videoFileList = [{
            name: file.name,
            url: result.data.fileResult.url
          }]

          this.$message.success('视频上传成功')
          this.getVideoDuration(result.data.fileResult.url)
          options.onSuccess(result)
        } else {
          console.error('合并响应数据格式错误:', result)
          throw new Error('文件合并失败：服务器返回数据格式错误')
        }
      } catch (error) {
        console.error('文件合并失败:', error)
        this.uploadStatus.progressStatus = 'exception'
        this.uploadStatus.message = '合并失败'

        let errorMessage = '未知错误'
        if (error && error.message) {
          errorMessage = error.message
        } else if (error && error.response && error.response.data) {
          errorMessage = error.response.data.message || error.response.data.msg || '服务器错误'
        }

        this.$message.error('文件合并失败：' + errorMessage)
        throw new Error(`文件合并失败: ${errorMessage}`)
      } finally {
        setTimeout(() => {
          this.uploadStatus.isUploading = false
          this.uploadStatus.canPause = false
        }, 1500)
      }
    },

    // 暂停上传
    pauseUpload() {
      this.uploadStatus.isPaused = true
      this.uploadStatus.message = '上传已暂停'
    },

    // 恢复上传
    resumeUpload() {
      if (this.uploadStatus.currentFile) {
        this.uploadStatus.isPaused = false
        this.uploadChunks(this.uploadStatus.currentFile, {
          onSuccess: () => {},
          onError: () => {}
        })
      }
    },

    // 取消上传
    cancelUpload() {
      if (this.uploadStatus.fileIdentifier) {
        cancelBigFileUploadApi(this.uploadStatus.fileIdentifier)
      }
      this.uploadStatus.isUploading = false
      this.uploadStatus.isPaused = false
      this.uploadStatus.canPause = false
      this.uploadStatus.percent = 0
      this.uploadStatus.message = '上传已取消'
      this.uploadStatus.currentFile = null
    },

    // 生成文件唯一标识符
    generateFileIdentifier(file) {
      const timestamp = Date.now()
      const random = Math.random().toString(36).substring(2)
      const fileName = file.name.replace(/[^a-zA-Z0-9]/g, '')
      return `${fileName}_${file.size}_${timestamp}_${random}`
    },

    // 格式化速度显示
    formatSpeed(bytesPerSecond) {
      if (bytesPerSecond < 1024) {
        return `${bytesPerSecond.toFixed(0)} B/s`
      } else if (bytesPerSecond < 1024 * 1024) {
        return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`
      } else {
        return `${(bytesPerSecond / (1024 * 1024)).toFixed(1)} MB/s`
      }
    },

    // 格式化时间显示
    formatTime(seconds) {
      if (seconds < 60) {
        return `${Math.round(seconds)}秒`
      } else if (seconds < 3600) {
        return `${Math.round(seconds / 60)}分钟`
      } else {
        return `${Math.round(seconds / 3600)}小时`
      }
    },
    // 视频加载错误处理
    handleVideoError(e) {
      console.error('视频加载错误:', e)

      // 获取更详细的错误信息
      let errorMessage = '未知错误'
      if (e.target && e.target.error) {
        switch (e.target.error.code) {
          case 1:
            errorMessage = '视频加载被中止'
            break
          case 2:
            errorMessage = '网络错误，无法下载视频'
            break
          case 3:
            errorMessage = '视频解码错误'
            break
          case 4:
            errorMessage = '视频格式不支持'
            break
        }
      }

      this.$message.error(`视频加载失败: ${errorMessage}`)
      this.$message.info('正在尝试使用备用方式播放...')
      this.switchToIframe(e)
    },
    // 在新窗口打开视频
    openVideoInNewTab() {
      if (this.previewVideoInfo && this.previewVideoInfo.videoUrl) {
        // 使用通用函数构建完整URL
        const url = this.getFileUrl(this.previewVideoInfo.videoUrl)
        window.open(url, '_blank')
      } else {
        this.$message.warning('没有可用的视频URL')
      }
    },
    // 切换到iframe方式
    switchToIframe(e) {
      console.error('视频标签加载失败，尝试使用iframe:', e)
      this.useIframe = true
    },
    // 下载视频
    downloadVideo() {
      if (this.previewVideoInfo && this.previewVideoInfo.videoUrl) {
        const url = this.getFileUrl(this.previewVideoInfo.videoUrl)
        const a = document.createElement('a')
        a.href = url
        a.download = this.previewVideoInfo.videoUrl.split('/').pop() || '视频文件.mp4'
        document.body.appendChild(a)
        a.click()
        document.body.removeChild(a)
      } else {
        this.$message.warning('没有可用的视频URL')
      }
    },
    tryDifferentUrl(command) {
      if (!this.previewVideoInfo || !this.previewVideoInfo.videoUrl) {
        this.$message.warning('没有可用的视频')
        return
      }

      const baseUrl = process.env.VUE_APP_BASE_API || 'http://127.0.0.1:20010/'
      let originalUrl = this.previewVideoInfo.videoUrl

      // 先清理URL，确保没有重复的协议头
      if (originalUrl.includes('http://') || originalUrl.includes('https://')) {
        const httpIndexes = []
        let index = -1
        while ((index = originalUrl.indexOf('http', index + 1)) !== -1) {
          httpIndexes.push(index)
        }

        if (httpIndexes.length > 1) {
          originalUrl = originalUrl.substring(httpIndexes[httpIndexes.length - 1])
        }
      }

      let newUrl = ''

      switch (command) {
        case 'format1':
          // 直接使用原始URL，不添加任何前缀
          newUrl = originalUrl
          break
        case 'format2':
          // 尝试移除COS URL中可能的多余部分
          if (originalUrl.includes('cos.ap-guangzhou.myqcloud.com')) {
            const parts = originalUrl.split('crmebimage')
            if (parts.length > 1) {
              newUrl = 'https://dong-1323115148.cos.ap-guangzhou.myqcloud.com/crmebimage' + parts[parts.length - 1]
            } else {
              newUrl = originalUrl
            }
          } else {
            newUrl = originalUrl
          }
          break
        case 'format3':
          // 如果不是外部URL，尝试添加api前缀
          if (!originalUrl.startsWith('http')) {
            newUrl = baseUrl + 'api/' + originalUrl
          } else {
            newUrl = originalUrl
          }
          break
        case 'format4':
          // 直接使用腾讯云URL的最简形式
          if (originalUrl.includes('cos.ap-guangzhou.myqcloud.com')) {
            const match = originalUrl.match(/https:\/\/dong-1323115148\.cos\.ap-guangzhou\.myqcloud\.com\/[^/]+\/(.+)/)
            if (match && match[1]) {
              newUrl = 'https://dong-1323115148.cos.ap-guangzhou.myqcloud.com/' + match[1]
            } else {
              newUrl = originalUrl
            }
          } else {
            newUrl = originalUrl
          }
          break
      }

      console.log('尝试新的URL格式:', newUrl)
      this.previewVideoUrl = newUrl
      this.useIframe = false // 重置为video标签尝试
    },
    formatFileUrl(url, forDisplay = true) {
      if (!url) return ''

      const baseUrl = process.env.VUE_APP_BASE_API || 'http://127.0.0.1:20010/'

      // 如果是为了显示(在浏览器中访问)
      if (forDisplay) {
        if (!url.startsWith('http')) {
          if (url.startsWith('file/')) {
            return baseUrl + 'api/' + url
          }
          return baseUrl + url
        }
        return url
      } else {
        // 如果是为了保存到数据库
        if (url.startsWith('http')) {
          // 移除域名和API前缀
          return url.replace(baseUrl + 'api/', '').replace(baseUrl, '')
        }
        return url
      }
    },
    // URL清理工具函数：移除重复的URL前缀
    cleanDuplicateUrl(url) {
      if (!url || !url.includes('http')) {
        return url
      }
      
      // 检查是否有重复的URL前缀
      const urlPattern = /https?:\/\/[^\s\/]+/g
      const domainMatches = url.match(urlPattern)
      
      if (domainMatches && domainMatches.length > 1) {
        // 如果有多个域名，说明URL重复了
        console.log('检测到重复的URL前缀:', domainMatches)
        
        // 找到最后一个完整的URL（从最后一个http开始）
        const lastHttpIndex = url.lastIndexOf('http')
        if (lastHttpIndex > 0) {
          const cleanedUrl = url.substring(lastHttpIndex)
          console.log('URL清理结果:', url, '->', cleanedUrl)
          return cleanedUrl
        }
      }
      
      return url
    },
    // 更健壮的文件URL处理
    getFileUrl(path) {
      if (!path) return ''

      // 如果已经是http/https开头的完整URL，直接返回
      if (path.startsWith('http')) {
        return path
      }

      // 否则，拼接基础URL
      const baseUrl = process.env.VUE_APP_BASE_API || 'http://127.0.0.1:20010'
      // 确保baseUrl末尾没有斜杠，path开头没有斜杠，然后用一个斜杠连接
      const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl
      const normalizedPath = path.startsWith('/') ? path.substring(1) : path

      return normalizedBaseUrl + '/' + normalizedPath
    },
    // 打开媒体库选择视频
    openMediaLibrary(type) {
      const _this = this
      this.$modalUpload(function(media) {
        if (media && media.length > 0) {
          let videoPath = media[0].sattDir
          console.log('原始视频路径:', videoPath)
          
          // 使用工具函数清理重复的URL前缀
          videoPath = _this.cleanDuplicateUrl(videoPath)
          
          // 设置选中的视频
          _this.temp.videoUrl = videoPath

          // 更新文件列表显示
          _this.videoFileList = [{
            name: videoPath.split('/').pop() || '视频文件.mp4',
            url: videoPath
          }]

          _this.$message.success('已选择视频')

          // 自动获取视频时长
          _this.getVideoDuration(videoPath)
        }
      }, '1', 'content', 'video/mp4')
    },
    // 打开媒体库选择图片
    openImageLibrary() {
      const _this = this
      this.$modalUpload(function(media) {
        console.log('选择的媒体数据:', media)
        if (media && media.length > 0) {
          let imagePath = media[0].sattDir
          console.log('原始图片路径:', imagePath)
          console.log('设置前的coverImage:', _this.temp.coverImage)
          
          // 使用工具函数清理重复的URL前缀
          imagePath = _this.cleanDuplicateUrl(imagePath)
          
          // 设置选中的图片作为封面
          _this.temp.coverImage = imagePath
          console.log('设置后的coverImage:', _this.temp.coverImage)
          _this.$message.success('已选择封面图片')
          // 强制更新视图
          _this.$forceUpdate()
        } else {
          console.log('没有选择任何媒体文件')
        }
      }, '1', 'content') // 不传第四个参数，默认选择图片
    },
    // 添加新方法：获取视频时长
    getVideoDuration(videoUrl) {
      if (!videoUrl) return

      const fullUrl = this.getFileUrl(videoUrl)
      console.log('获取视频时长URL:', fullUrl)

      const video = document.createElement('video')
      video.style.display = 'none'
      video.preload = 'metadata' // 优化：只加载元数据
      video.crossOrigin = 'anonymous' // 添加跨域支持
      video.muted = true // 静音以避免自动播放限制

      // 添加超时机制
      const timeout = setTimeout(() => {
        console.warn('获取视频时长超时')
        this.$message.warning('获取视频时长超时，请手动设置')
        if (video.parentNode) {
          document.body.removeChild(video)
        }
      }, 10000) // 10秒超时

      video.addEventListener('loadedmetadata', () => {
        clearTimeout(timeout)
        const duration = Math.round(video.duration)
        console.log('视频时长（秒）:', duration)
        this.temp.duration = duration
        const minutes = Math.floor(duration / 60)
        const seconds = duration % 60
        this.videoDuration = new Date(0, 0, 0, 0, minutes, seconds)
        if (video.parentNode) {
          document.body.removeChild(video)
        }
      })

      video.addEventListener('error', (e) => {
        clearTimeout(timeout)
        console.error('获取视频时长失败:', e)
        console.error('视频URL:', fullUrl)
        console.error('错误详情:', {
          error: e.target.error,
          networkState: e.target.networkState,
          readyState: e.target.readyState
        })
        
        // 尝试使用备用方法获取时长
        this.getVideoDurationFallback(fullUrl)
        
        if (video.parentNode) {
          document.body.removeChild(video)
        }
      })

      video.addEventListener('loadstart', () => {
        console.log('开始加载视频元数据')
      })

      video.addEventListener('progress', () => {
        console.log('视频加载进度更新')
      })

      video.src = fullUrl
      document.body.appendChild(video)
    },

    // 备用方法：使用fetch检查文件是否存在
    async getVideoDurationFallback(videoUrl) {
      try {
        console.log('尝试备用方法检查视频文件')
        const response = await fetch(videoUrl, { 
          method: 'HEAD',
          headers: {
            'Authorization': localStorage.getItem('token') || ''
          }
        })
        
        if (response.ok) {
          console.log('视频文件存在，但无法获取时长，可能是编码问题')
          this.$message.warning('视频文件存在但无法自动获取时长，请手动设置。可能是视频编码格式不兼容。')
        } else {
          console.error('视频文件不存在或无法访问，状态码:', response.status)
          this.$message.error(`视频文件无法访问 (HTTP ${response.status})，请检查文件是否正确上传`)
        }
      } catch (error) {
        console.error('备用检查失败:', error)
        this.$message.warning('无法访问视频文件，请检查服务器配置或手动设置时长')
      }
    },
    // 视频加载完成，获取实际时长
    onVideoLoaded(e) {
      if (e.target && !this.temp.duration && this.previewVideoInfo === this.temp) {
        const duration = Math.round(e.target.duration)
        if (duration > 0) {
          console.log('从预览视频获取时长:', duration)

          // 只有在编辑当前项目时才更新表单
          this.temp.duration = duration

          // 更新时间选择器
          const minutes = Math.floor(duration / 60)
          const seconds = duration % 60
          this.videoDuration = new Date(0, 0, 0, 0, minutes, seconds)
        }
      }
    },
    handleVideoLoadStart() {
      console.log('视频开始加载')
    },
    handleVideoCanPlay() {
      console.log('视频可以播放')
    },
    // 格式化文件大小显示
    formatFileSize(bytes) {
      if (bytes < 1024) {
        return bytes + ' B'
      } else if (bytes < 1024 * 1024) {
        return (bytes / 1024).toFixed(1) + ' KB'
      } else if (bytes < 1024 * 1024 * 1024) {
        return (bytes / (1024 * 1024)).toFixed(1) + ' MB'
      } else {
        return (bytes / (1024 * 1024 * 1024)).toFixed(1) + ' GB'
      }
    },
    // 备用方案：使用原来的API方法但添加必需参数
    uploadSmallFileBackup(file, options) {
      this.uploadStatus.isUploading = true
      this.uploadStatus.percent = 0
      this.uploadStatus.progressStatus = 'active'
      this.uploadStatus.message = '准备上传...'

      // 创建FormData对象并添加所有必需参数
      const formData = new FormData()
      formData.append('file', file)
      formData.append('model', 'course')  // 添加缺少的model参数
      formData.append('pid', '1')         // 添加pid参数
      formData.append('type', file.type || 'video/mp4')  // 添加文件类型

      // 模拟上传进度
      this.uploadProgressTimer = setInterval(() => {
        if (this.uploadStatus.percent < 90) {
          this.uploadStatus.percent += Math.floor(Math.random() * 10)
          this.uploadStatus.message = `上传中 ${this.uploadStatus.percent}%...`
        }
      }, 500)

      // 调用API函数
      fileFileApi(formData).then(res => {
        clearInterval(this.uploadProgressTimer)
        this.uploadStatus.percent = 100
        this.uploadStatus.progressStatus = 'success'
        this.uploadStatus.message = '上传完成'

        if (res.code === 200 && res.data && res.data.url) {
          this.temp.videoUrl = res.data.url
          this.videoFileList = [{
            name: file.name,
            url: res.data.url
          }]
          this.$message.success('视频上传成功')
          
          // 自动获取视频时长
          this.getVideoDuration(res.data.url)
          
          options.onSuccess(res)
        } else {
          this.uploadStatus.progressStatus = 'exception'
          this.uploadStatus.message = '上传失败：' + (res.msg || '未知错误')
          this.$message.error('上传失败：' + (res.msg || '未知错误'))
          options.onError(new Error(res.msg || '上传失败'))
        }

        setTimeout(() => {
          this.uploadStatus.isUploading = false
        }, 1500)
      }).catch(err => {
        clearInterval(this.uploadProgressTimer)
        this.uploadStatus.progressStatus = 'exception'
        this.uploadStatus.message = '上传失败'
        this.$message.error('上传失败：' + (err.message || '未知错误'))
        options.onError(err)
        
        setTimeout(() => {
          this.uploadStatus.isUploading = false
        }, 1500)
      })
    },
    // 检查服务器连接状态
    checkServerStatus() {
      this.$message.info('正在检查服务器连接...')
      
      const baseUrl = process.env.VUE_APP_BASE_API || 'http://127.0.0.1:20010'
      const testUrl = baseUrl.replace(/\/+$/, '') + '/admin/upload/file'
      
      // 使用HEAD请求测试连接
      fetch(testUrl, {
        method: 'HEAD',
        headers: {
          'Authorization': localStorage.getItem('token') || ''
        }
      }).then(response => {
        if (response.ok || response.status === 405) { // 405表示方法不允许，但服务器在运行
          this.$message.success('服务器连接正常')
        } else {
          this.$message.error(`服务器响应异常：HTTP ${response.status}`)
        }
      }).catch(error => {
        console.error('服务器连接测试失败:', error)
        this.$message.error('无法连接到服务器，请检查服务是否运行')
      })
    },
    
    getUploadUrl() {
      const baseUrl = process.env.VUE_APP_BASE_API || 'http://127.0.0.1:20010'
      return baseUrl.replace(/\/+$/, '') + '/admin/upload/file'
    },
    
    hasToken() {
      return !!localStorage.getItem('token')
    }
  }
}
</script>

<style scoped>
.breadcrumb-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

.course-info-box {
  display: flex;
  margin-bottom: 20px;
  padding: 15px;
  background-color: #f9f9f9;
  border-radius: 4px;
}

.course-image {
  width: 120px;
  height: 80px;
  margin-right: 15px;
  overflow: hidden;
  border-radius: 4px;
}

.course-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.course-details {
  flex: 1;
}

.course-title {
  margin: 0 0 10px 0;
  font-size: 18px;
  color: #333;
}

.course-meta {
  display: flex;
  margin-bottom: 10px;
}

.course-meta span {
  margin-right: 15px;
  font-size: 13px;
  color: #666;
}

.course-desc {
  font-size: 13px;
  color: #666;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.episode-title {
  font-weight: bold;
}

.ml-5 {
  margin-left: 5px;
}

.video-preview {
  position: relative;
  width: 160px;
  height: 90px;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  margin: 0 auto;
}

.video-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.play-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 40px;
  height: 40px;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  opacity: 0.8;
  transition: opacity 0.3s;
}

.video-preview:hover .play-icon {
  opacity: 1;
}

.play-icon i {
  font-size: 20px;
}

.duration-badge {
  position: absolute;
  bottom: 5px;
  right: 5px;
  padding: 2px 5px;
  background-color: rgba(0, 0, 0, 0.6);
  border-radius: 2px;
  color: #fff;
  font-size: 12px;
}

.form-container {
  margin: 0 auto;
}

.upload-tip {
  font-size: 12px;
  color: #909399;
  margin-top: 5px;
}

.form-tip {
  margin-left: 10px;
  font-size: 13px;
  color: #909399;
}

.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}

.avatar-uploader-icon {
  width: 178px;
  height: 100px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 28px;
  color: #8c939d;
  background-color: #f5f7fa;
}

.upload-text {
  font-size: 12px;
  margin-top: 5px;
}

.avatar {
  width: 178px;
  height: 100px;
  display: block;
  object-fit: cover;
}

.video-uploader {
  width: 100%;
}

.video-uploader .el-upload {
  width: 100%;
}

.file-upload-status {
  margin-top: 15px;
}

.preview-video-container {
  position: relative;
  width: 100%;
  height: 200px;
  overflow: hidden;
  border-radius: 4px;
  margin-bottom: 10px;
}

.preview-cover {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.preview-play-icon {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 60px;
  height: 60px;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 30px;
  cursor: pointer;
  transition: transform 0.2s;
}

.preview-play-icon:hover {
  transform: translate(-50%, -50%) scale(1.1);
}

.video-info-overlay {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 10px;
  background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
  color: white;
}

.video-title {
  margin: 0;
  font-size: 14px;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.video-duration {
  margin: 5px 0 0;
  font-size: 12px;
}

.video-preview-dialog .el-dialog__body {
  padding: 0;
}

.video-container {
  width: 100%;
  background-color: #000;
}

.preview-video-player {
  width: 100%;
  max-height: 450px;
  display: block;
}

.empty-video {
  height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #909399;
}

.empty-video i {
  font-size: 50px;
  margin-bottom: 10px;
}

.video-info {
  padding: 20px;
}

.video-info h3 {
  margin: 0 0 10px 0;
  font-size: 18px;
}

.video-info p {
  margin: 0 0 15px 0;
  color: #666;
  font-size: 14px;
  line-height: 1.6;
}

.video-meta {
  display: flex;
  color: #909399 !important;
  font-size: 13px !important;
}

.video-meta span {
  margin-right: 15px;
}

.draggable-row {
  cursor: move;
}

.debug-area {
  margin-top: 20px;
  border-top: 1px dashed #eee;
  padding-top: 10px;
}

.debug-buttons {
  display: flex;
  justify-content: flex-start;
  margin-bottom: 10px;
}

.debug-buttons .el-button {
  margin-right: 15px;
}

.help-content {
  background-color: #f8f9fa;
  padding: 10px 15px;
  border-radius: 4px;
  margin-top: 10px;
  font-size: 13px;
}

.help-content h4 {
  margin-top: 0;
  margin-bottom: 10px;
  font-size: 14px;
  color: #606266;
}

.help-content ol {
  padding-left: 20px;
  margin: 10px 0;
}

.help-content p {
  margin: 10px 0 5px;
}

.empty-data {
  margin: 40px 0;
  text-align: center;
}

.preview-info {
  font-size: 12px;
  color: #606266;
  margin-top: 5px;
  word-break: break-all;
}

.media-selector {
  display: flex;
  align-items: center;
}

.select-area {
  width: 200px;
  height: 120px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-right: 10px;
}

.select-area:hover {
  border-color: #409EFF;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #8c939d;
}

.upload-placeholder i {
  font-size: 28px;
  margin-bottom: 8px;
}

.upload-placeholder p {
  font-size: 14px;
  margin: 0;
}

.media-preview {
  width: 100%;
  height: 100%;
  position: relative;
}

.preview-video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media-info {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0,0,0,0.6);
  color: white;
  font-size: 12px;
  padding: 2px 5px;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

.clear-btn {
  margin-left: 10px;
}

.upLoadPicBox {
  width: 100px;
  height: 100px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.upLoadPicBox:hover {
  border-color: #409EFF;
}

.pictrue {
  width: 100%;
  height: 100%;
  position: relative;
}

.pictrue img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 4px;
}

.upLoad {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #8c939d;
}

.upLoad i {
  font-size: 28px;
  margin-bottom: 8px;
}

.upLoad p {
  font-size: 14px;
  margin: 0;
}

.big-file-upload-info {
  margin-top: 10px;
  padding: 10px;
  background-color: #f8f9fa;
  border-radius: 4px;
  border: 1px dashed #d9d9d9;
}

.upload-details {
  margin-bottom: 10px;
}

.upload-controls {
  margin-top: 10px;
  display: flex;
  justify-content: flex-end;
}

.upload-controls .el-button {
  margin-left: 10px;
}

.video-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 100%;
  min-height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.video-uploader .el-upload:hover {
  border-color: #409EFF;
}

.video-preview-box {
  width: 100%;
  max-width: 300px;
  text-align: center;
}

.preview-video {
  width: 100%;
  max-height: 150px;
  border-radius: 4px;
}

.video-info {
  margin-top: 8px;
  font-size: 12px;
  color: #666;
  word-break: break-all;
}

.upload-actions {
  margin-top: 8px;
  text-align: center;
}
</style>
